"""
代理连接测试工具

用于测试SOCKS5和HTTP代理的连通性和稳定性
"""

import asyncio
import time
from typing import Dict, Any, Optional, List
import aiohttp
from playwright.async_api import async_playwright
from config.settings import ProxyConfig
from utils.logger import get_logger
from exceptions.exceptions import NetworkException

logger = get_logger(__name__)


class ProxyTester:
    """代理测试器"""
    
    def __init__(self):
        self.test_urls = [
            "https://httpbin.org/ip",
            "https://api.ipify.org?format=json",
            "https://www.baidu.com",
        ]
    
    async def test_proxy_connectivity(self, proxy_config: ProxyConfig) -> Dict[str, Any]:
        """
        测试代理连通性
        
        Args:
            proxy_config: 代理配置
            
        Returns:
            Dict: 测试结果
        """
        result = {
            "proxy_type": proxy_config.type,
            "proxy_server": f"{proxy_config.host}:{proxy_config.port}",
            "success": False,
            "response_time": None,
            "ip_info": None,
            "error": None,
            "test_details": []
        }
        
        if not proxy_config.enabled:
            result["error"] = "代理未启用"
            return result
        
        try:
            # 使用aiohttp测试HTTP代理
            if proxy_config.type in ["http", "https"]:
                result = await self._test_http_proxy(proxy_config, result)
            else:
                # 使用Playwright测试SOCKS5代理
                result = await self._test_socks_proxy(proxy_config, result)
                
        except Exception as e:
            result["error"] = str(e)
            logger.error(f"代理测试失败: {str(e)}")
        
        return result
    
    async def _test_http_proxy(self, proxy_config: ProxyConfig, result: Dict[str, Any]) -> Dict[str, Any]:
        """测试HTTP代理"""
        proxy_url = f"http://{proxy_config.host}:{proxy_config.port}"
        
        async with aiohttp.ClientSession() as session:
            for test_url in self.test_urls:
                test_detail = {
                    "url": test_url,
                    "success": False,
                    "response_time": None,
                    "error": None
                }
                
                try:
                    start_time = time.time()
                    
                    async with session.get(
                        test_url,
                        proxy=proxy_url,
                        timeout=aiohttp.ClientTimeout(total=10)
                    ) as response:
                        response_time = time.time() - start_time
                        
                        if response.status == 200:
                            test_detail["success"] = True
                            test_detail["response_time"] = response_time
                            
                            # 尝试获取IP信息
                            if "ip" in test_url.lower():
                                try:
                                    ip_data = await response.json()
                                    result["ip_info"] = ip_data
                                except:
                                    result["ip_info"] = await response.text()
                        else:
                            test_detail["error"] = f"HTTP {response.status}"
                            
                except Exception as e:
                    test_detail["error"] = str(e)
                
                result["test_details"].append(test_detail)
        
        # 判断整体成功率
        successful_tests = sum(1 for detail in result["test_details"] if detail["success"])
        if successful_tests > 0:
            result["success"] = True
            avg_response_time = sum(
                detail["response_time"] for detail in result["test_details"] 
                if detail["response_time"]
            ) / successful_tests
            result["response_time"] = avg_response_time
        
        return result
    
    async def _test_socks_proxy(self, proxy_config: ProxyConfig, result: Dict[str, Any]) -> Dict[str, Any]:
        """测试SOCKS代理"""
        proxy_server = f"{proxy_config.type}://{proxy_config.host}:{proxy_config.port}"
        
        playwright = await async_playwright().start()
        
        try:
            browser = await playwright.chromium.launch(
                headless=True,
                proxy={"server": proxy_server}
            )
            
            context = await browser.new_context()
            page = await context.new_page()
            
            for test_url in self.test_urls:
                test_detail = {
                    "url": test_url,
                    "success": False,
                    "response_time": None,
                    "error": None
                }
                
                try:
                    start_time = time.time()
                    
                    response = await page.goto(test_url, timeout=10000)
                    response_time = time.time() - start_time
                    
                    if response and response.status == 200:
                        test_detail["success"] = True
                        test_detail["response_time"] = response_time
                        
                        # 尝试获取IP信息
                        if "ip" in test_url.lower():
                            try:
                                content = await page.content()
                                if "origin" in content or "ip" in content:
                                    result["ip_info"] = content
                            except:
                                pass
                    else:
                        test_detail["error"] = f"HTTP {response.status if response else 'No response'}"
                        
                except Exception as e:
                    test_detail["error"] = str(e)
                
                result["test_details"].append(test_detail)
            
            await browser.close()
            
        finally:
            await playwright.stop()
        
        # 判断整体成功率
        successful_tests = sum(1 for detail in result["test_details"] if detail["success"])
        if successful_tests > 0:
            result["success"] = True
            avg_response_time = sum(
                detail["response_time"] for detail in result["test_details"] 
                if detail["response_time"]
            ) / successful_tests
            result["response_time"] = avg_response_time
        
        return result
    
    async def test_proxy_stability(self, proxy_config: ProxyConfig, test_count: int = 5) -> Dict[str, Any]:
        """
        测试代理稳定性
        
        Args:
            proxy_config: 代理配置
            test_count: 测试次数
            
        Returns:
            Dict: 稳定性测试结果
        """
        results = []
        
        for i in range(test_count):
            logger.info(f"执行第 {i+1}/{test_count} 次稳定性测试")
            result = await self.test_proxy_connectivity(proxy_config)
            results.append(result)
            
            # 间隔1秒
            await asyncio.sleep(1)
        
        # 计算稳定性统计
        successful_tests = sum(1 for r in results if r["success"])
        success_rate = successful_tests / test_count * 100
        
        response_times = [r["response_time"] for r in results if r["response_time"]]
        avg_response_time = sum(response_times) / len(response_times) if response_times else None
        
        stability_result = {
            "test_count": test_count,
            "successful_tests": successful_tests,
            "success_rate": success_rate,
            "avg_response_time": avg_response_time,
            "min_response_time": min(response_times) if response_times else None,
            "max_response_time": max(response_times) if response_times else None,
            "detailed_results": results
        }
        
        logger.info(f"代理稳定性测试完成: 成功率 {success_rate:.1f}%")
        
        return stability_result
    
    async def test_multiple_proxies(self, proxy_configs: List[ProxyConfig]) -> Dict[str, Any]:
        """
        测试多个代理配置
        
        Args:
            proxy_configs: 代理配置列表
            
        Returns:
            Dict: 多代理测试结果
        """
        results = {}
        
        for i, proxy_config in enumerate(proxy_configs):
            proxy_name = f"{proxy_config.type}_{proxy_config.host}_{proxy_config.port}"
            logger.info(f"测试代理 {i+1}/{len(proxy_configs)}: {proxy_name}")
            
            result = await self.test_proxy_connectivity(proxy_config)
            results[proxy_name] = result
        
        # 统计最佳代理
        successful_proxies = {name: result for name, result in results.items() if result["success"]}
        
        best_proxy = None
        if successful_proxies:
            best_proxy = min(
                successful_proxies.items(),
                key=lambda x: x[1]["response_time"] or float('inf')
            )[0]
        
        summary = {
            "total_proxies": len(proxy_configs),
            "successful_proxies": len(successful_proxies),
            "best_proxy": best_proxy,
            "detailed_results": results
        }
        
        return summary


async def test_current_proxy_config(proxy_config: ProxyConfig) -> None:
    """
    测试当前代理配置的便捷函数
    
    Args:
        proxy_config: 代理配置
    """
    tester = ProxyTester()
    
    logger.info("开始测试代理连通性...")
    connectivity_result = await tester.test_proxy_connectivity(proxy_config)
    
    if connectivity_result["success"]:
        logger.info(f"✅ 代理连通性测试成功")
        logger.info(f"   响应时间: {connectivity_result['response_time']:.2f}秒")
        if connectivity_result["ip_info"]:
            logger.info(f"   IP信息: {connectivity_result['ip_info']}")
        
        # 进行稳定性测试
        logger.info("开始测试代理稳定性...")
        stability_result = await tester.test_proxy_stability(proxy_config, test_count=3)
        
        logger.info(f"✅ 代理稳定性测试完成")
        logger.info(f"   成功率: {stability_result['success_rate']:.1f}%")
        logger.info(f"   平均响应时间: {stability_result['avg_response_time']:.2f}秒")
        
    else:
        logger.error(f"❌ 代理连通性测试失败: {connectivity_result['error']}")
        for detail in connectivity_result["test_details"]:
            if detail["error"]:
                logger.error(f"   {detail['url']}: {detail['error']}")